// LockFreeStack.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "LockFreeStack.h"
#include <iostream>

DWORD WINAPI ThreadFunc(LPVOID stack)
{
    LockFreeStack<int>* freeLockStack = (LockFreeStack<int>*)stack;
    for (int i = 0; i < 20000; ++i)
    {
        freeLockStack->Push(i);
    }

    return 0;
}

DWORD WINAPI ThreadFuncShow(LPVOID stack)
{
    LockFreeStack<int>* freeLockStack = (LockFreeStack<int>*)stack;

    for (size_t i = 0; i < 20000; ++i)
    { 
        std::auto_ptr<int> value(freeLockStack->Pop());
        if (value.get())
        {
            std::cout << *value << " ";
        }
    }
    std::cout << std::endl;

    return 0;
}

// This program used LockFreeStack only Multi Write Single Read
// If you uncomment the code you will get an exception about deleting a memory
int _tmain(int argc, _TCHAR* argv[])
{
    LockFreeStack<int> freeLockStack;

    DWORD dwThreadId = 0;
    HANDLE hThreadPush1 = CreateThread(NULL, 0,    ThreadFunc, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
    HANDLE hThreadPush2 = CreateThread(NULL, 0,    ThreadFunc, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
    HANDLE hThreadPush3 = CreateThread(NULL, 0,    ThreadFunc, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);

    HANDLE hThreadShow1 = CreateThread(NULL, 0,    ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
//     HANDLE hThreadShow2 = CreateThread(NULL, 0,    ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
//     HANDLE hThreadShow3 = CreateThread(NULL, 0,    ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);

    ResumeThread(hThreadPush1);
    ResumeThread(hThreadPush2);
    ResumeThread(hThreadPush3);

    WaitForSingleObject(hThreadPush1, INFINITE);
    WaitForSingleObject(hThreadPush2, INFINITE);
    WaitForSingleObject(hThreadPush3, INFINITE);

    ResumeThread(hThreadShow1);
//     ResumeThread(hThreadShow2);
//     ResumeThread(hThreadShow3);

    WaitForSingleObject(hThreadShow1, INFINITE);
//     WaitForSingleObject(hThreadShow2, INFINITE);
//     WaitForSingleObject(hThreadShow3, INFINITE);
    CloseHandle(hThreadPush1);
    CloseHandle(hThreadPush2);
    CloseHandle(hThreadPush3);
    CloseHandle(hThreadShow1);
//     CloseHandle(hThreadShow2);
//     CloseHandle(hThreadShow3);
    return 0;
}

